home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_023 / ver30 / tty / ansi / tty.c next >
C/C++ Source or Header  |  1992-05-06  |  7KB  |  343 lines

  1. /*
  2.  * Name:    MicroEMACS
  3.  *        Digital ANSI terminal display
  4.  * Version:    29
  5.  * Last edit:    10-Feb-86
  6.  * By:        rex::conroy
  7.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  8.  *
  9.  * The SCALD display is just an ANSI display, with
  10.  * some special hacks to kludge around the bugs, and
  11.  * to make it a bit more friendly. The support is
  12.  * unquestionably non-optimal. The costs are wrong; in
  13.  * fact, display should be fixed up to understand non
  14.  * linear cost devices like the SCALD. The BackIndex
  15.  * sequence used in the insert line is defective in
  16.  * the display firmware, so we set the cost high to
  17.  * discourage its use. Perhaps the cost should be
  18.  * set to infinity!
  19.  */
  20. #include    "def.h"
  21.  
  22. #define    SCALD    0            /* Buggy display.        */
  23.  
  24. #define    BEL    0x07            /* BEL character.        */
  25. #define    ESC    0x1B            /* ESC character.        */
  26. #define    LF    0x0A            /* Line feed.            */
  27.  
  28. extern    int    ttrow;
  29. extern    int    ttcol;
  30. extern    int    tttop;
  31. extern    int    ttbot;
  32. extern    int    tthue;
  33.  
  34. #if    SCALD
  35.  
  36. int    tceeol    =    3;        /* Costs, SCALDstation.        */
  37. int    tcinsl    =     100;
  38. int    tcdell    =    100;
  39.  
  40. #else
  41.  
  42. int    tceeol    =    3;        /* Costs, ANSI display.        */
  43. int    tcinsl    =     17;
  44. int    tcdell    =    16;
  45.  
  46. #endif
  47.  
  48. /*
  49.  * Initialize the terminal when the editor
  50.  * gets started up. This is a no-op on the ANSI
  51.  * display. On the SCALD display, it turns off the
  52.  * half-screen scroll, because this appears to really
  53.  * confuse the scrolling region firmware in the
  54.  * display.
  55.  */
  56. ttinit()
  57. {
  58. #if    SCALD
  59.     ttputc(ESC);            /* Cancel jump interval.    */
  60.     ttputc('[');
  61.     asciiparm(1);
  62.     ttputc('j');
  63. #endif
  64. }
  65.  
  66. /*
  67.  * Clean up the terminal, in anticipation of
  68.  * a return to the command interpreter. This is a no-op
  69.  * on the ANSI display. On the SCALD display, it sets the
  70.  * window back to half screen scrolling. Perhaps it should
  71.  * query the display for the increment, and put it
  72.  * back to what it was.
  73.  */
  74. tttidy()
  75. {
  76. #if    SCALD
  77.     ttputc(ESC);            /* Half screen.            */
  78.     ttputc('[');
  79.     asciiparm(nrow/2);
  80.     ttputc('j');
  81. #endif
  82. }
  83.  
  84. /*
  85.  * Move the cursor to the specified
  86.  * origin 0 row and column position. Try to
  87.  * optimize out extra moves; redisplay may
  88.  * have left the cursor in the right
  89.  * location last time!
  90.  */
  91. ttmove(row, col)
  92. {
  93.     if (ttrow!=row || ttcol!=col) {
  94.         ttputc(ESC);
  95.         ttputc('[');
  96.         asciiparm(row+1);
  97.         ttputc(';');
  98.         asciiparm(col+1);
  99.         ttputc('H');
  100.         ttrow = row;
  101.         ttcol = col;
  102.     }
  103. }
  104.  
  105. /*
  106.  * Erase to end of line.
  107.  */
  108. tteeol()
  109. {
  110.     ttputc(ESC);
  111.     ttputc('[');
  112.     ttputc('K');
  113. }
  114.  
  115. /*
  116.  * Erase to end of page.
  117.  */
  118. tteeop()
  119. {
  120.     ttputc(ESC);
  121.     ttputc('[');
  122.     ttputc('J');
  123. }
  124.  
  125. /*
  126.  * Make a noise.
  127.  */
  128. ttbeep()
  129. {
  130.     ttputc(BEL);
  131.     ttflush();
  132. }
  133.  
  134. /*
  135.  * Convert a number to decimal
  136.  * ascii, and write it out. Used to
  137.  * deal with numeric arguments.
  138.  */
  139. asciiparm(n)
  140. register int    n;
  141. {
  142.     register int    q;
  143.  
  144.     q = n/10;
  145.     if (q != 0)
  146.         asciiparm(q);
  147.     ttputc((n%10) + '0');
  148. }
  149.  
  150. /*
  151.  * Insert a block of blank lines onto the
  152.  * screen, using a scrolling region that starts at row
  153.  * "row" and extends down to row "bot". Deal with the one
  154.  * line case, which is a little bit special, with special
  155.  * case code. Put all of the back index commands out
  156.  * in a block. The SCALDstation loses the position
  157.  * of the cursor.
  158.  */
  159. ttinsl(row, bot, nchunk)
  160. {
  161.     if (row == bot) {            /* Funny case.        */
  162.         if (nchunk != 1)
  163.             abort();
  164.         ttmove(row, 0);
  165.         tteeol();
  166.     } else {                /* General case.    */
  167.         ttwindow(row, bot);
  168.         ttmove(row, 0);
  169.         while (nchunk--) {
  170.             ttputc(ESC);        /* Back index.        */
  171.             ttputc('M');
  172.         }
  173. #if    SCALD
  174.         ttrow = HUGE;
  175.         ttcol = HUGE;
  176. #endif
  177.     }
  178. }
  179.  
  180. /*
  181.  * Delete a block of lines, with the uppermost
  182.  * line at row "row", in a screen slice that extends to
  183.  * row "bot". The "nchunk" is the number of lines that have
  184.  * to be deleted. Watch for the pathalogical 1 line case,
  185.  * where the scroll region is *not* the way to do it.
  186.  * The block delete is used by the slightly more
  187.  * optimal display code.
  188.  */
  189. ttdell(row, bot, nchunk)
  190. {
  191.     if (row == bot) {            /* Funny case.        */
  192.         if (nchunk != 1)
  193.             abort();
  194.         ttmove(row, 0);
  195.         tteeol();
  196.     } else {                /* General case.    */
  197.         ttwindow(row, bot);
  198.         ttmove(bot, 0);
  199.         while (nchunk--)
  200.             ttputc(LF);
  201. #if    SCALD
  202.         ttrow = HUGE;
  203.         ttcol = HUGE;
  204. #endif
  205.     }
  206. }
  207.  
  208. /*
  209.  * This routine sets the scrolling window
  210.  * on the display to go from line "top" to line
  211.  * "bot" (origin 0, inclusive). The caller checks
  212.  * for the pathalogical 1 line scroll window that
  213.  * doesn't work right, and avoids it. The "ttrow"
  214.  * and "ttcol" variables are set to a crazy value
  215.  * to ensure that the next call to "ttmove" does
  216.  * not turn into a no-op (the window adjustment
  217.  * moves the cursor).
  218.  */
  219. ttwindow(top, bot)
  220. {
  221.     if (tttop!=top || ttbot!=bot) {
  222.         ttputc(ESC);
  223.         ttputc('[');
  224.         asciiparm(top+1);
  225.         ttputc(';');
  226.         asciiparm(bot+1);
  227.         ttputc('r');
  228.         ttrow = HUGE;            /* Unknown.        */
  229.         ttcol = HUGE;
  230.         tttop = top;            /* Remember region.    */
  231.         ttbot = bot;
  232.     }
  233. }
  234.  
  235. /*
  236.  * Switch to full screen scroll. This is
  237.  * used by "spawn.c" just before is suspends the
  238.  * editor, and by "display.c" when it is getting ready
  239.  * to exit. This function gets to full screen scroll
  240.  * by sending a DECSTBM with default parameters, but
  241.  * I think that this is wrong. The SRM seems to say
  242.  * that the default for Pb is 24, not the size of the
  243.  * screen, which seems really dumb. Do I really have
  244.  * to read the size of the screen as in "ttresize"
  245.  * to do this right?
  246.  */
  247. ttnowindow()
  248. {
  249.     ttputc(ESC);
  250.     ttputc('[');
  251.     ttputc(';');
  252.     ttputc('r');
  253.     ttrow = HUGE;                /* Unknown.        */
  254.     ttcol = HUGE;
  255.     tttop = HUGE;                /* No scroll region.    */
  256.     ttbot = HUGE;
  257. }
  258.  
  259. /*
  260.  * Set the current writing color to the
  261.  * specified color. Watch for color changes that are
  262.  * not going to do anything (the color is already right)
  263.  * and don't send anything to the display.
  264.  * The rainbow version does this in putline.s on a
  265.  * line by line basis, so don't bother sending
  266.  * out the color shift.
  267.  */
  268. ttcolor(color)
  269. register int    color;
  270. {
  271.     if (color != tthue) {
  272. /*
  273. if    !RAINBOW
  274. */
  275.         if (color == CTEXT) {        /* Normal video.    */
  276.             ttputc(ESC);
  277.             ttputc('[');
  278.             ttputc('m');
  279.         } else if (color == CMODE) {    /* Reverse video.    */
  280.             ttputc(ESC);
  281.             ttputc('[');
  282.             ttputc('7');
  283.             ttputc('m');
  284.         }
  285. /*
  286. endif
  287. */
  288.         tthue = color;            /* Save the color.    */
  289.     }
  290. }
  291.  
  292. /*
  293.  * This routine is called by the
  294.  * "refresh the screen" command to try and resize
  295.  * the display. The new size, which must be deadstopped
  296.  * to not exceed the NROW and NCOL limits, it stored
  297.  * back into "nrow" and "ncol". Display can always deal
  298.  * with a screen NROW by NCOL. Look in "window.c" to
  299.  * see how the caller deals with a change.
  300.  */
  301. ttresize()
  302. {
  303.     register int    c;
  304.     register int    newnrow;
  305.     register int    newncol;
  306.  
  307.     ttputc(ESC);                /* Off the end of the    */
  308.     ttputc('[');                /* world. The terminal    */
  309.     asciiparm(HUGE);            /* will chop it.    */
  310.     ttputc(';');
  311.     asciiparm(HUGE);
  312.     ttputc('H');
  313.     ttrow = HUGE;                /* Unknown.        */
  314.     ttcol = HUGE;
  315.     ttputc(ESC);                /* Report position.    */
  316.     ttputc('[');
  317.     ttputc('6');
  318.     ttputc('n');
  319.     ttflush();
  320.     if (ttgetc()!=ESC || ttgetc()!='[')
  321.         return;
  322.     newnrow = 0;
  323.     while ((c=ttgetc())>='0' && c<='9')
  324.         newnrow = 10*newnrow + c - '0';
  325.     if (c != ';')
  326.         return;
  327.     newncol = 0;
  328.     while ((c=ttgetc())>='0' && c<='9')
  329.         newncol = 10*newncol + c - '0';
  330.     if (c != 'R')
  331.         return;
  332.     if (newnrow < 1)            /* Check limits.    */
  333.         newnrow = 1;
  334.     else if (newnrow > NROW)
  335.         newnrow = NROW;
  336.     if (newncol < 1)
  337.         newncol = 1;
  338.     else if (newncol > NCOL)
  339.         newncol = NCOL;
  340.     nrow = newnrow;
  341.     ncol = newncol;
  342. }
  343.